// Output created by jacc on Sat Jun 09 16:53:27 CEST 2012

package it.unicam.cs.cosy.bioshape.core.behaviours;

import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import java.util.ArrayList;

import java.io.IOException;
import java.io.Serializable;
import java.io.StringReader;

import hermesV3.util.HermesLogger;

import it.unicam.cs.cosy.bioshape.core.components.Pair;

/**
 * Parsing class created using <a href="http
 * ://web.cecs.pdx.edu/~mpj/jacc/index.html">Jacc</a> parser generator.
 * Recognises a Shape Calculus behaviour and stores its information through the
 * {@code parse()} method. See the linked site for the user manual and other
 * information.
 * 
 * @author Federico Buti
 */

public class SCParser implements Serializable, SCParserTokens {
	/** Auto-generated Serial ID */
	private static final long serialVersionUID = -4211116920054153677L;
	private int yyss = 100;
	private int yytok;
	private int yysp = 0;
	private int[] yyst;
	protected int yyerrno = (-1);
	private Object[] yysv;
	private Object yyrv;

	/**
	 * @return {@code true} if the parsing is completed successfully,
	 *         {@code false} otherwise
	 */
	@SuppressWarnings("fallthrough")
	public boolean parse() {
		int yyn = 0;
		yysp = 0;
		yyst = new int[yyss];
		yysv = new Object[yyss];
		yytok = (lexer.token);
		for (;;) {
			switch (yyn) {
			case 0:
				yyst[yysp] = 0;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
				//$FALL-THROUGH$
			case 52:
				switch (yytok) {
				case ENDINPUT:
				case PROC_VAR:
					yyn = yyr2();
					continue;
				}
				yyn = 107;
				continue;

			case 1:
				yyst[yysp] = 1;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 53:
				switch (yytok) {
				case ENDINPUT:
					yyn = 104;
					continue;
				case PROC_VAR:
					yyn = 2;
					continue;
				}
				yyn = 107;
				continue;

			case 2:
				yyst[yysp] = 2;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 54:
				switch (yytok) {
				case '=':
					yyn = 3;
					continue;
				}
				yyn = 107;
				continue;

			case 3:
				yyst[yysp] = 3;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 55:
				yyn = yys3();
				continue;

			case 4:
				yyst[yysp] = 4;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 56:
				switch (yytok) {
				case '+':
					yyn = 13;
					continue;
				case ';':
					yyn = 14;
					continue;
				}
				yyn = 107;
				continue;

			case 5:
				yyst[yysp] = 5;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 57:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr4();
					continue;
				}
				yyn = 107;
				continue;

			case 6:
				yyst[yysp] = 6;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 58:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr5();
					continue;
				}
				yyn = 107;
				continue;

			case 7:
				yyst[yysp] = 7;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 59:
				switch (yytok) {
				case '(':
					yyn = 15;
					continue;
				}
				yyn = 107;
				continue;

			case 8:
				yyst[yysp] = 8;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 60:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr10();
					continue;
				}
				yyn = 107;
				continue;

			case 9:
				yyst[yysp] = 9;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 61:
				switch (yytok) {
				case '(':
					yyn = 16;
					continue;
				}
				yyn = 107;
				continue;

			case 10:
				yyst[yysp] = 10;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 62:
				switch (yytok) {
				case '(':
					yyn = 17;
					continue;
				}
				yyn = 107;
				continue;

			case 11:
				yyst[yysp] = 11;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 63:
				yyn = yys11();
				continue;

			case 12:
				yyst[yysp] = 12;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 64:
				switch (yytok) {
				case NAME:
					yyn = 19;
					continue;
				}
				yyn = 107;
				continue;

			case 13:
				yyst[yysp] = 13;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 65:
				yyn = yys13();
				continue;

			case 14:
				yyst[yysp] = 14;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 66:
				switch (yytok) {
				case ENDINPUT:
				case PROC_VAR:
					yyn = yyr1();
					continue;
				}
				yyn = 107;
				continue;

			case 15:
				yyst[yysp] = 15;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 67:
				switch (yytok) {
				case NAME:
					yyn = 21;
					continue;
				}
				yyn = 107;
				continue;

			case 16:
				yyst[yysp] = 16;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 68:
				switch (yytok) {
				case '<':
					yyn = 23;
					continue;
				}
				yyn = 107;
				continue;

			case 17:
				yyst[yysp] = 17;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 69:
				switch (yytok) {
				case DOUBLE:
					yyn = 24;
					continue;
				}
				yyn = 107;
				continue;

			case 18:
				yyst[yysp] = 18;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 70:
				switch (yytok) {
				case '+':
					yyn = 13;
					continue;
				case ')':
					yyn = 25;
					continue;
				}
				yyn = 107;
				continue;

			case 19:
				yyst[yysp] = 19;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 71:
				switch (yytok) {
				case ',':
					yyn = 26;
					continue;
				}
				yyn = 107;
				continue;

			case 20:
				yyst[yysp] = 20;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 72:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr3();
					continue;
				}
				yyn = 107;
				continue;

			case 21:
				yyst[yysp] = 21;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 73:
				switch (yytok) {
				case ',':
					yyn = 27;
					continue;
				}
				yyn = 107;
				continue;

			case 22:
				yyst[yysp] = 22;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 74:
				switch (yytok) {
				case ')':
					yyn = 28;
					continue;
				case ',':
					yyn = 29;
					continue;
				}
				yyn = 107;
				continue;

			case 23:
				yyst[yysp] = 23;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 75:
				switch (yytok) {
				case NAME:
					yyn = 30;
					continue;
				}
				yyn = 107;
				continue;

			case 24:
				yyst[yysp] = 24;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 76:
				switch (yytok) {
				case ')':
					yyn = 31;
					continue;
				}
				yyn = 107;
				continue;

			case 25:
				yyst[yysp] = 25;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 77:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr11();
					continue;
				}
				yyn = 107;
				continue;

			case 26:
				yyst[yysp] = 26;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 78:
				switch (yytok) {
				case NAME:
					yyn = 32;
					continue;
				}
				yyn = 107;
				continue;

			case 27:
				yyst[yysp] = 27;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 79:
				switch (yytok) {
				case NAME:
					yyn = 33;
					continue;
				}
				yyn = 107;
				continue;

			case 28:
				yyst[yysp] = 28;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 80:
				switch (yytok) {
				case '.':
					yyn = 34;
					continue;
				}
				yyn = 107;
				continue;

			case 29:
				yyst[yysp] = 29;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 81:
				switch (yytok) {
				case '<':
					yyn = 35;
					continue;
				}
				yyn = 107;
				continue;

			case 30:
				yyst[yysp] = 30;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 82:
				switch (yytok) {
				case ',':
					yyn = 36;
					continue;
				}
				yyn = 107;
				continue;

			case 31:
				yyst[yysp] = 31;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 83:
				switch (yytok) {
				case '.':
					yyn = 37;
					continue;
				}
				yyn = 107;
				continue;

			case 32:
				yyst[yysp] = 32;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 84:
				switch (yytok) {
				case '>':
					yyn = 38;
					continue;
				}
				yyn = 107;
				continue;

			case 33:
				yyst[yysp] = 33;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 85:
				switch (yytok) {
				case ')':
					yyn = 39;
					continue;
				}
				yyn = 107;
				continue;

			case 34:
				yyst[yysp] = 34;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 86:
				yyn = yys34();
				continue;

			case 35:
				yyst[yysp] = 35;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 87:
				switch (yytok) {
				case NAME:
					yyn = 41;
					continue;
				}
				yyn = 107;
				continue;

			case 36:
				yyst[yysp] = 36;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 88:
				switch (yytok) {
				case NAME:
					yyn = 42;
					continue;
				}
				yyn = 107;
				continue;

			case 37:
				yyst[yysp] = 37;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 89:
				yyn = yys37();
				continue;

			case 38:
				yyst[yysp] = 38;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 90:
				switch (yytok) {
				case '.':
					yyn = 44;
					continue;
				}
				yyn = 107;
				continue;

			case 39:
				yyst[yysp] = 39;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 91:
				switch (yytok) {
				case '.':
					yyn = 45;
					continue;
				}
				yyn = 107;
				continue;

			case 40:
				yyst[yysp] = 40;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 92:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr8();
					continue;
				}
				yyn = 107;
				continue;

			case 41:
				yyst[yysp] = 41;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 93:
				switch (yytok) {
				case ',':
					yyn = 46;
					continue;
				}
				yyn = 107;
				continue;

			case 42:
				yyst[yysp] = 42;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 94:
				switch (yytok) {
				case '>':
					yyn = 47;
					continue;
				}
				yyn = 107;
				continue;

			case 43:
				yyst[yysp] = 43;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 95:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr9();
					continue;
				}
				yyn = 107;
				continue;

			case 44:
				yyst[yysp] = 44;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 96:
				yyn = yys44();
				continue;

			case 45:
				yyst[yysp] = 45;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 97:
				yyn = yys45();
				continue;

			case 46:
				yyst[yysp] = 46;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 98:
				switch (yytok) {
				case NAME:
					yyn = 50;
					continue;
				}
				yyn = 107;
				continue;

			case 47:
				yyst[yysp] = 47;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 99:
				switch (yytok) {
				case ')':
				case ',':
					yyn = yyr13();
					continue;
				}
				yyn = 107;
				continue;

			case 48:
				yyst[yysp] = 48;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 100:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr6();
					continue;
				}
				yyn = 107;
				continue;

			case 49:
				yyst[yysp] = 49;
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 101:
				switch (yytok) {
				case ')':
				case ';':
				case '+':
					yyn = yyr7();
					continue;
				}
				yyn = 107;
				continue;

			case 50:
				yyst[yysp] = 50;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 102:
				switch (yytok) {
				case '>':
					yyn = 51;
					continue;
				}
				yyn = 107;
				continue;

			case 51:
				yyst[yysp] = 51;
				yysv[yysp] = (lexer.semanticValue);
				yytok = (nextToken());
				if (++yysp >= yyst.length) {
					yyexpand();
				}
			case 103:
				switch (yytok) {
				case ')':
				case ',':
					yyn = yyr12();
					continue;
				}
				yyn = 107;
				continue;

			case 104:
				return true;
			case 105:
				yyerror("stack overflow");
			case 106:
				return false;
			case 107:
				yyerror("syntax error");
				return false;
			}
		}
	}

	protected void yyexpand() {
		int[] newyyst = new int[2 * yyst.length];
		Object[] newyysv = new Object[2 * yyst.length];
		for (int i = 0; i < yyst.length; i++) {
			newyyst[i] = yyst[i];
			newyysv[i] = yysv[i];
		}
		yyst = newyyst;
		yysv = newyysv;
	}

	private int yys3() {
		switch (yytok) {
		case NIL:
			return 6;
		case OMEGA:
			return 7;
		case PROC_VAR:
			return 8;
		case RHO:
			return 9;
		case TIME:
			return 10;
		case '(':
			return 11;
		case '<':
			return 12;
		}
		return 107;
	}

	private int yys11() {
		switch (yytok) {
		case NIL:
			return 6;
		case OMEGA:
			return 7;
		case PROC_VAR:
			return 8;
		case RHO:
			return 9;
		case TIME:
			return 10;
		case '(':
			return 11;
		case '<':
			return 12;
		}
		return 107;
	}

	private int yys13() {
		switch (yytok) {
		case NIL:
			return 6;
		case OMEGA:
			return 7;
		case PROC_VAR:
			return 8;
		case RHO:
			return 9;
		case TIME:
			return 10;
		case '(':
			return 11;
		case '<':
			return 12;
		}
		return 107;
	}

	private int yys34() {
		switch (yytok) {
		case NIL:
			return 6;
		case OMEGA:
			return 7;
		case PROC_VAR:
			return 8;
		case RHO:
			return 9;
		case TIME:
			return 10;
		case '(':
			return 11;
		case '<':
			return 12;
		}
		return 107;
	}

	private int yys37() {
		switch (yytok) {
		case NIL:
			return 6;
		case OMEGA:
			return 7;
		case PROC_VAR:
			return 8;
		case RHO:
			return 9;
		case TIME:
			return 10;
		case '(':
			return 11;
		case '<':
			return 12;
		}
		return 107;
	}

	private int yys44() {
		switch (yytok) {
		case NIL:
			return 6;
		case OMEGA:
			return 7;
		case PROC_VAR:
			return 8;
		case RHO:
			return 9;
		case TIME:
			return 10;
		case '(':
			return 11;
		case '<':
			return 12;
		}
		return 107;
	}

	private int yys45() {
		switch (yytok) {
		case NIL:
			return 6;
		case OMEGA:
			return 7;
		case PROC_VAR:
			return 8;
		case RHO:
			return 9;
		case TIME:
			return 10;
		case '(':
			return 11;
		case '<':
			return 12;
		}
		return 107;
	}

	private int yyr1() { // PROC_DEF : PROC_DEF PROC_VAR '=' Proc_Expr ';'
		{
			// verify that the behaviour string is not duplicated (same string
			// differente variable)
			String variable = this.getVariable(((Behaviour) yysv[yysp - 2])
					.getLabel());
			if (variable != null) {
				errMsg = "Behaviour '"
						+ ((Behaviour) yysv[yysp - 2]).getLabel()
						+ "' already defined with variable " + "'" + variable
						+ "'";
				return error;
			}
			if (listOfStrings.containsValue(((Behaviour) yysv[yysp - 2])
					.getLabel())) {
				outputInfo(HermesLogger.ERROR, "SCParser - process "
						+ ((String) yysv[yysp - 4])
						+ " with a different process variable...");
				return error;
			}
			// loading of the new read behaviour into the BehaviourTable
			// structure...
			Variable top = new Variable(((String) yysv[yysp - 4]),
					((Behaviour) yysv[yysp - 2]));
			if (!behTable.addRow(((String) yysv[yysp - 4]), top, dependencies)) {
				outputInfo(HermesLogger.ERROR, "SCParser - variable '"
						+ ((String) yysv[yysp - 4]) + "' defined repeatedly");
				return error;
			}
			// otherwise continie by cleaning the dependencies structure for the
			// next behaviour string
			dependencies.clear();
			// increase the built rows...
			this.built_rows++;
			//
			// save the behaviour string
			listOfStrings.put(((String) yysv[yysp - 4]),
					((Behaviour) yysv[yysp - 2]).getLabel());
			outputInfo(HermesLogger.INFO,
					"Process Successfully Acquired  ---->  "
							+ ((String) yysv[yysp - 4]) + " = "
							+ ((Behaviour) yysv[yysp - 2]).getLabel());
		}
		yysv[yysp -= 5] = yyrv;
		return 1;
	}

	private int yyr2() { // PROC_DEF : /* empty */
		{
			// DO NOTHING
		}
		yysv[yysp -= 0] = yyrv;
		return 1;
	}

	private int yyr12() { // Channels_List : Channels_List ',' '<' NAME ',' NAME
							// '>'
		{
			Pair<String, String> pair = new Pair<String, String>(
					((String) yysv[yysp - 4]), ((String) yysv[yysp - 2]));
			if (!pairs.contains(pair))
				pairs.add(pair);
			else {
				errMsg = "Channel \"<"
						+ ((String) yysv[yysp - 4])
						+ ", "
						+ ((String) yysv[yysp - 2])
						+ ">\" doubly defined. Please reconsider your behaviours.";
				return error;
			}
		}
		yysv[yysp -= 7] = yyrv;
		return 22;
	}

	private int yyr13() { // Channels_List : '<' NAME ',' NAME '>'
		{
			Pair<String, String> pair = new Pair<String, String>(
					((String) yysv[yysp - 4]), ((String) yysv[yysp - 2]));
			if (!pairs.contains(pair))
				pairs.add(pair);
			else {
				errMsg = "Channel \"<"
						+ ((String) yysv[yysp - 4])
						+ ", "
						+ ((String) yysv[yysp - 2])
						+ ">\" doubly defined. Please reconsider your behaviours.";
				return error;
			}
		}
		yysv[yysp -= 5] = yyrv;
		return 22;
	}

	private int yyr3() { // Proc_Expr : Proc_Expr '+' Sim_Expr
		{
			if (((Behaviour) yysv[yysp - 3]) instanceof Choice
					&& ((Behaviour) yysv[yysp - 1]) instanceof Choice)
				yyrv = new Choice((Choice) ((Behaviour) yysv[yysp - 3]),
						(Choice) ((Behaviour) yysv[yysp - 1]));
			else if (((Behaviour) yysv[yysp - 3]) instanceof Choice)
				yyrv = new Choice((Choice) ((Behaviour) yysv[yysp - 3]),
						((Behaviour) yysv[yysp - 1]));
			else if (((Behaviour) yysv[yysp - 1]) instanceof Choice)
				yyrv = new Choice(((Behaviour) yysv[yysp - 3]),
						(Choice) ((Behaviour) yysv[yysp - 1]));
			else
				yyrv = new Choice(((Behaviour) yysv[yysp - 3]),
						((Behaviour) yysv[yysp - 1]));

		}
		yysv[yysp -= 3] = yyrv;
		return yypProc_Expr();
	}

	private int yyr4() { // Proc_Expr : Sim_Expr
		{
			yyrv = yysv[yysp - 1];

		}
		yysv[yysp -= 1] = yyrv;
		return yypProc_Expr();
	}

	private int yypProc_Expr() {
		switch (yyst[yysp - 1]) {
		case 3:
			return 4;
		default:
			return 18;
		}
	}

	private int yyr5() { // Sim_Expr : NIL
		{
			yyrv = new Nil();
		}
		yysv[yysp -= 1] = yyrv;
		return yypSim_Expr();
	}

	private int yyr6() { // Sim_Expr : '<' NAME ',' NAME '>' '.' Sim_Expr
		{
			if (!sites.containsKey(yysv[yysp - 4])) {
				errMsg = "Active site named \"" + ((String) yysv[yysp - 4])
						+ "\" undefined in the input file. Parsing aborted.";
				return error;
			}
			yyrv = new ActionPrefix(((String) yysv[yysp - 6]),
					sites.get(yysv[yysp - 3]), ((Behaviour) yysv[yysp - 1]));
		}
		yysv[yysp -= 7] = yyrv;
		return yypSim_Expr();
	}

	private int yyr7() { // Sim_Expr : OMEGA '(' NAME ',' NAME ')' '.' Sim_Expr
		{
			if (!sites.containsKey(yysv[yysp - 4])) {
				errMsg = "Active site named \"" + yysv[yysp - 5]
						+ "\" undefined in the input file. Parsing aborted.";
				return error;
			}
			yyrv = new WeakSplit(((String) yysv[yysp - 6]),
					sites.get(yysv[yysp - 4]), ((Behaviour) yysv[yysp - 1]));
		}
		yysv[yysp -= 8] = yyrv;
		return yypSim_Expr();
	}

	private int yyr8() { // Sim_Expr : RHO '(' Channels_List ')' '.' Sim_Expr
		{
			StrongSplit s = new StrongSplit(pairs, ((Behaviour) yysv[yysp - 1]));
			pairs.clear();
			yyrv = s;
		}
		yysv[yysp -= 6] = yyrv;
		return yypSim_Expr();
	}

	private int yyr9() { // Sim_Expr : TIME '(' DOUBLE ')' '.' Sim_Expr
		{
			yyrv = new Delay(((Double) yysv[yysp - 4]).doubleValue(),
					((Behaviour) yysv[yysp - 1]));
		}
		yysv[yysp -= 6] = yyrv;
		return yypSim_Expr();
	}

	private int yyr10() { // Sim_Expr : PROC_VAR
		{
			Variable v = new Variable(((String) yysv[yysp - 1]));
			if (!dependencies.contains(v))
				dependencies.add(v);
			yyrv = v;
		}
		yysv[yysp -= 1] = yyrv;
		return yypSim_Expr();
	}

	private int yyr11() { // Sim_Expr : '(' Proc_Expr ')'
		{
			yyrv = yysv[yysp - 2];
		}
		yysv[yysp -= 3] = yyrv;
		return yypSim_Expr();
	}

	private int yypSim_Expr() {
		switch (yyst[yysp - 1]) {
		case 45:
			return 49;
		case 44:
			return 48;
		case 37:
			return 43;
		case 34:
			return 40;
		case 13:
			return 20;
		default:
			return 5;
		}
	}

	protected String[] yyerrmsgs = {};

	// TEST EXAMPLES
	// ---> F = delay(2).nil + delay(5).nil + <a, BOH>.K;
	// ---> F = delay(2).nil + delay(5).nil + ssplit(<a,BOH>, <b,BOH>,
	// <c,BOH>).K;

	/** Reference to the used lexical analyzer instance. */
	private SCLexer lexer;

	/** number of the built rows. */
	private int built_rows = 0;

	/** {@code String} containing an error message if any occurs. */
	private String errMsg = "";

	/**
	 * List of {@code Pair} objects representing a couple channel name / channel
	 * features set
	 */
	private ArrayList<Pair<String, String>> pairs = new ArrayList<Pair<String, String>>();

	/** Contains all the processes parsed. */
	BehavioursTable behTable = new BehavioursTable();

	/**
	 * @return the behTable
	 */
	public BehavioursTable getBehTable() {
		return behTable;
	}

	/**
	 * Contains the dependencies (the process variables contained) in the
	 * currectly parsed processes.
	 */
	private ArrayList<Behaviour> dependencies = new ArrayList<Behaviour>();

	/** <code>HashMap</code> with a list of all the parsed processes. */
	private HashMap<String, String> listOfStrings = new HashMap<String, String>();

	/** <code>HashMap</code> with a list of all the available {@code ActiveSite}. */
	private Map<String, ActiveSite> sites;

	/**
	 * Builds a Parser instance starting from the chosen lexical analyzer and a
	 * list of {@code ActiveSite} objects. The latter is used to check that the
	 * sites declared in the behaviours are actually defined. Note that NO check
	 * is done among
	 * 
	 * @param input
	 *            The text to be parsed
	 * @param sites
	 *            The available {@code ActiveSite} objects defined in the input.
	 */
	public SCParser(String input, Map<String, ActiveSite> sites) {
		this.lexer = new SCLexer(new StringReader(input));
		try {
			lexer.yylex();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (BehaviourException e) {
            e.printStackTrace();
        }
		this.sites = sites;
	}

	/**
	 * Returns the number of read rows which are BUILT at the time this method
	 * is called.
	 * 
	 * @return an integer number representing the read BUILT rows
	 */
	public int getBuiltRows() {
		return built_rows;
	}

	/**
	 * Returns the number of read rows at the time this method is called.
	 * 
	 * @return an integer number representing the read rows
	 */
	public int getRows() {
		return lexer.linenr();
	}

	/**
	 * Returns the Shape calculus agent associated with the passed process
	 * variable.
	 * 
	 * @param variable
	 *            to search
	 * @return the behaviour string associated to the passed variable or
	 *         <code>null</code> if no mapping is found.
	 */
	public String getString(String variable) {
		if (listOfStrings.containsKey(variable))
			return listOfStrings.get(variable);
		return null;
	}

	/**
	 * Returns the process variable associated with the passed process.
	 * 
	 * @param process
	 *            to search
	 * @return the behaviour string associated to the passed variable or
	 *         <code>null</code> if no mapping is found.
	 */
	public String getVariable(String process) {
		Set<String> keys = listOfStrings.keySet();
		for (String key : keys) {
			if (listOfStrings.get(key).equalsIgnoreCase(process))
				return key;
		}
		return null;
	}

	/**
	 * Error function called from the parser for syntax error in the token
	 * input. If an incorrect token (i.e. an unrecognizable token) is found from
	 * the lexer or else when "error" token is returned in the semantics meaning
	 * the tokens found are not acceptable in the particular context.
	 */
	private void yyerror(String msg) {
		String err = "";
		if (!errMsg.isEmpty()) {
			err = err + errMsg;
			err = err + " at line " + lexer.linenr() + 1;
		} else {
			if (Character.codePointAt(lexer.yytext().toCharArray(), 0) != '?') {
				err = err
						+ (msg + " at line " + (lexer.linenr() + 1)
								+ " and at column " + (lexer.columnnr() + 1)
								+ " with character(s) '" + lexer.yytext() + "'.\n");
			} else
				err = err
						+ (msg + " at line " + (lexer.linenr() + 1)
								+ " and at column " + (lexer.columnnr() + 1) + ".\n");
		}
		//
		outputInfo(HermesLogger.ERROR, err.toString());
	}

	/**
	 * Called from the parser to get the next available token.
	 * 
	 * @return the <code>integer</code> value associated with the next token or
	 *         the <code>error token</code> if an error occurs, or
	 *         <code>endofinput token</code> if no more token are available
	 */
	private int nextToken() {
		try {
			return lexer.yylex();
		} catch (Exception e) {
			return error;
		}
	}

	/**
	 * Used internally to set the field containing the error verified during
	 * parsing process. This field could be read subsequently for error report
	 * purposes
	 * 
	 * @param text
	 *            <code>String</code> containing the encountered error
	 */
	private void outputInfo(int level, String text) {
		HermesLogger.log(level, this.getClass().getSimpleName() + " - " + text);
	}
}